-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Fix uint overflow bugs in std::{at_vec, vec, str} #9108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
LGTM. I'm ok with the perf hit. |
Most of the removal of unsafe code and simplification is because I don't want to check for overflow everywhere. It's messy, and we can let boundary checks or |
Bounds checking sounds like a good candidate for a __builtin_expect-style function that hints to the branch predictor to assume we'll almost always not overflow when resizing. Do we have anything like that in the compiler, and if not, how hard would it be to add it? |
More importantly: how much impact would it actually have? On Wed, Sep 11, 2013 at 6:25 PM, Erick Tryzelaar
|
+1 to branch prediction hints; conversation that convinced me at https://botbot.me/mozilla/rust/msg/5945880/ |
I'm very skeptical of branch prediction hints generally. It's not uncommon to annotate them incorrectly, or for them to be useless. |
I have a feeling that LLVM's branch prediction hints don't do much when you aren't optimizing for size. |
it's not an important part. More important would be to reduce the number of places we need to check for overflow |
Like next_power_of_two, but returns None on overflow.
Rebased to avoid conflicts (new name of I changed I changed With these changes, it looks like the I'm not sure if I'm benchmarking this correctly. It could be that .connect() just optimizes to the point of invalidating the benchmark with the changes, but that's a win in itself.. with local
I'm not sure if the benchmarks should stay in the PR, but apart from that I think this change is ready for review & merge. |
Regarding branch predicition, since the overflow check is now inside a rarely taken |
Updated the PR text (because this information will show in the merge message, so I want it to be correct) |
Now the stage2 bench is done for before and after:
|
Issue #8742 Add the method `.reserve_additional(n: uint)`: Check for overflow in self.len() + n, and reserve that many elements (rounded up to next power of two). Does nothing if self.len() + n < self.capacity() already.
`push_bytes` is implemented with `ptr::copy_memory` here since this function is intended to be used to implement `.push_str()` for str, so we want to avoid the overhead.
/// Access the str in its vector representation. | ||
/// The caller must preserve the valid UTF-8 property when modifying. | ||
#[inline] | ||
pub unsafe fn as_owned_vec<U>(s: &mut ~str, f: &fn(&mut ~[u8]) -> U) -> U { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be expressed as fn as_owned_vec<'a>(s: &'a mut ~str) -> &'a mut ~[u8]
?
This looks good to me! Sad to see a positive diff stat, but I guess that's what happens when you write tests :) r+ with my comment |
Incorporated your suggestion, also found one place where |
…hton Fix uint overflow bugs in std::{at_vec, vec, str} Closes #8742 Fix issue #8742, which summarized is: unsafe code in vec and str did assume that a reservation for `X + Y` elements always succeeded, and didn't overflow. Introduce the method `Vec::reserve_additional(n)` to make it easy to check for overflow in `Vec::push` and `Vec::push_all`. In std::str, simplify and remove a lot of the unsafe code and use `push_str` instead. With improvements to `.push_str` and the new function `vec::bytes::push_bytes`, it looks like this change has either no or positive impact on performance. I believe there are many places still where `v.reserve(A + B)` still can overflow. This by itself is not an issue unless followed by (unsafe) code that steps aside boundary checks.
…xFrednet Remove trailing spaces Closes rust-lang#9108 changelog: remove trailing spaces, which are not allowed by the JSON standard.
Fix uint overflow bugs in std::{at_vec, vec, str}
Closes #8742
Fix issue #8742, which summarized is: unsafe code in vec and str did assume
that a reservation for
X + Y
elements always succeeded, and didn't overflow.Introduce the method
Vec::reserve_additional(n)
to make it easy to check foroverflow in
Vec::push
andVec::push_all
.In std::str, simplify and remove a lot of the unsafe code and use
push_str
instead. With improvements to
.push_str
and the new functionvec::bytes::push_bytes
, it looks like this change has either no or positiveimpact on performance.
I believe there are many places still where
v.reserve(A + B)
still can overflow.This by itself is not an issue unless followed by (unsafe) code that steps aside
boundary checks.